home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / MPW_TOOL / TOOLS / TOOLS_WI / BYACC__ / READER.C < prev    next >
C/C++ Source or Header  |  1989-11-19  |  25KB  |  1,297 lines

  1. #include <stdio.h>
  2. #include "defs.h"
  3. #include "dep.h"
  4. #include "files.h"
  5. #include "gram.h"
  6. #include "new.h"
  7. #include "symtab.h"
  8. #include "text.h"
  9. #include "tokens.h"
  10.  
  11. extern int lineno;
  12. extern YYSTYPE yylval;
  13. extern char dflag;
  14. extern char vflag;
  15.  
  16. typedef
  17.   struct rhs_cell
  18.     {
  19.       struct rhs_cell *next;
  20.       struct bucket *symbol;
  21.     }
  22.   rhs_cell;
  23.  
  24. typedef
  25.   struct rule_cell
  26.     {
  27.       struct rule_cell *next;
  28.       struct bucket *lhs;
  29.       struct rhs_cell *rhs;
  30.       short prec;
  31.       char assoc;
  32.     }
  33.   rule_cell;
  34.  
  35. LOCAL bucket *goal;
  36. LOCAL bucket *augmenting_symbol;
  37. LOCAL unsigned *numbers_used;
  38. LOCAL text *stype;
  39. LOCAL rule_cell *grammar;
  40. LOCAL rule_cell *last_rule;
  41. LOCAL rhs_cell *last_symbol;
  42. LOCAL int rhslen;
  43. LOCAL short prec;
  44. LOCAL char assoc;
  45. LOCAL char type_flag;
  46. LOCAL bucket *lhs;
  47. LOCAL int actname_count;
  48.  
  49. copy_section(fp)
  50. register FILE *fp;
  51. {
  52.   register int c;
  53.  
  54.   c = getc(parser_file);
  55.   while (c != '@' && c != EOF)
  56.     {
  57.       putc(c, fp);
  58.       c = getc(parser_file);
  59.       if (c == '@')
  60.     {
  61.       c = getc(parser_file);
  62.       if (c != '@')
  63.         putc('@', fp);
  64.     }
  65.     }
  66. }
  67.  
  68. declare(bp, tag, value, prec, assoc, class, used)
  69. register bucket *bp;
  70. char *tag;
  71. short value;
  72. short prec;
  73. char assoc;
  74. char class;
  75. char used;
  76. {
  77.     if (tag != NIL(char))
  78.     {
  79.     if (bp->tag != NIL(char) && bp->tag != tag)
  80.         retyped_warning(bp);
  81.     bp->tag = tag;
  82.     }
  83.  
  84.     if (value != UNDEFINED)
  85.     {
  86.     if ( ! BIT(numbers_used, value))
  87.     {
  88.         SETBIT(numbers_used, value);
  89.         if (bp->value == UNDEFINED)
  90.         bp->value = value;
  91.         else if (bp->value != value)
  92.         revalued_warning(bp);
  93.     }
  94.       else if (bp->value != value)
  95.     value_error(value);
  96.     }
  97.  
  98.   if (prec != 0)
  99.     {
  100.       if (bp->prec == 0)
  101.     bp->prec = prec;
  102.       else
  103.     reprec_warning(bp);
  104.     }
  105.  
  106.   if (assoc != 0)
  107.     bp->assoc = assoc;
  108.  
  109.   if (bp->class == UNKNOWN)
  110.     bp->class = class;
  111.   else if (class == TERMINAL)
  112.     {
  113.       if (bp->class == UNKNOWN)
  114.     bp->class = TERMINAL;
  115.       else if (class == NONTERMINAL)
  116.     terminal_start(bp);
  117.     }
  118.  
  119.   if (used)
  120.     bp->used = 1;
  121. }
  122.  
  123. int
  124. declare_tokens(assoc, prec, used)
  125. char assoc;
  126. short prec;
  127. char used;
  128. {
  129.   register int tok;
  130.   register char *tag;
  131.   register int done;
  132.   register bucket *bp;
  133.   static char token_msg[] = "malformed %token declaration";
  134.   static char prec_msg[] = "malformed precedence decaration";
  135.  
  136.   tag = NIL(char);
  137.   tok = yylex();
  138.   if (tok == TYPE_IDENTIFIER)
  139.     {
  140.       tag = yylval.bp->key;
  141.       tok = yylex();
  142.     }
  143.  
  144.   done = 0;
  145.   while ( ! done)
  146.     {
  147.       if (tok != IDENTIFIER && tok != CHARACTER && tok != STRING)
  148.     {
  149.       if (assoc == TOKEN)
  150.         error(lineno, token_msg);
  151.       else
  152.         error(lineno, prec_msg);
  153.     }
  154.       while (tok == IDENTIFIER || tok == CHARACTER || tok == STRING)
  155.     {
  156.       bp = yylval.bp;
  157.       tok = yylex();
  158.       if (tok != NUMBER)
  159.         declare(bp, tag, UNDEFINED, prec, assoc, TERMINAL, used);
  160.       else
  161.         {
  162.           declare(bp, tag, yylval.i, prec, assoc, TERMINAL, used);
  163.           tok = yylex();
  164.         }
  165.     }
  166.       if (tok == COMMA)
  167.     tok = yylex();
  168.       else
  169.     done = 1;
  170.     }
  171.  
  172.   return (tok);
  173. }
  174.  
  175. int
  176. declare_type()
  177. {
  178.   register int tok;
  179.   register char *tag;
  180.   register int done;
  181.   static char malformed_msg[] = "malformed %type declaration";
  182.  
  183.   tok = yylex();
  184.   if (tok != TYPE_IDENTIFIER)
  185.     error(lineno, malformed_msg);
  186.  
  187.   tag = yylval.bp->key;
  188.   tok = yylex();
  189.   done = 0;
  190.   while ( ! done)
  191.     {
  192.       if (tok != IDENTIFIER && tok != CHARACTER && tok != STRING)
  193.     error(lineno, malformed_msg);
  194.       while (tok == IDENTIFIER || tok == CHARACTER || tok == STRING)
  195.     {
  196.       declare(yylval.bp, tag, UNDEFINED, 0, 0, UNKNOWN, 1);
  197.           tok = yylex();
  198.     }
  199.       if (tok == COMMA)
  200.     tok = yylex();
  201.       else
  202.     done = 1;
  203.     }
  204.   return (tok);
  205. }
  206.  
  207. read_declarations()
  208. {
  209.   register int tok;
  210.   register int prlevel;
  211.   static char no_grammar_msg[] = "grammar not found";
  212.   static char bad_start_msg[] = "malformed %start declaration";
  213.   static char reunion_msg[] = "multiple %union declarations";
  214.   static char malformed_msg[] = "malformed declaration";
  215.  
  216.   prlevel = 0;
  217.   tok = yylex();
  218.   while(tok != MARK)
  219.     {
  220.       switch (tok)
  221.     {
  222.     case END_OF_FILE:
  223.       error(lineno, no_grammar_msg);
  224.  
  225.     case TEXT:
  226.       write_text(yylval.tp, action_file);
  227.       free_text(yylval.tp);
  228.       tok = yylex();
  229.       break;
  230.  
  231.     case TOKEN:
  232.       tok = declare_tokens(tok, 0, 1);
  233.       break;
  234.  
  235.     case LEFT:
  236.     case RIGHT:
  237.     case NONASSOC:
  238.       prlevel++;
  239.       tok = declare_tokens(tok, prlevel, 0);
  240.       break;
  241.  
  242.     case TYPE:
  243.       type_flag = 1;
  244.       tok = declare_type();
  245.       break;
  246.  
  247.     case START:
  248.       tok = yylex();
  249.       if (tok != IDENTIFIER)
  250.         error(lineno, bad_start_msg);
  251.       goal = yylval.bp;
  252.       declare(yylval.bp, NIL(char), UNDEFINED, 0, 0, NONTERMINAL, 0);
  253.       tok = yylex();
  254.       break;
  255.  
  256.     case UNION_TEXT:
  257.       if (stype != NIL(text))
  258.         error(lineno, reunion_msg);
  259.       stype = yylval.tp;
  260.       tok = yylex();
  261.       break;
  262.  
  263.     default:
  264.       error(lineno, malformed_msg);
  265.     }
  266.     }
  267. }
  268.  
  269. define_error_code()
  270. {
  271.     if (first_symbol->value == UNDEFINED)
  272.     first_symbol->value = MAXCHAR + 1;
  273.     fprintf(action_file, "\n#define\tYYERRCODE\t%d\n", first_symbol->value);
  274. }
  275.  
  276. define_stype()
  277. {
  278.   if (stype != NIL(text))
  279.     write_text(stype, action_file);
  280.   else if (!type_flag)
  281.     {
  282.       fprintf(action_file, "\n#ifndef\tYYSTYPE\n");
  283.       fprintf(action_file, "typedef\tint\tYYSTYPE;\n");
  284.       fprintf(action_file, "#endif");
  285.     }
  286. }
  287.  
  288. initialize_grammar()
  289. {
  290.   register bucket *bp;
  291.   register rule_cell *rp;
  292.   register rhs_cell *rhsp;
  293.  
  294.   bp = augmenting_symbol;
  295.   bp->class = NONTERMINAL;
  296.   bp->tag = goal->tag;
  297.   bp->value = 0;
  298.   bp->used = 1;
  299.  
  300.   grammar = rp = NEW(rule_cell);
  301.   last_rule = rp;
  302.   rp->lhs = bp;
  303.   rp->rhs = rhsp = NEW(rhs_cell);
  304.   rhsp->symbol = goal;
  305.   nrules = 1;
  306.   nvars = 1;
  307.   assoc = 0;
  308.   prec = 0;
  309. }
  310.  
  311. add_rule(bp)
  312. register bucket *bp;
  313. {
  314.   register rule_cell *rp;
  315.   static char lhs_msg[] = "a token appears on the lhs of a rule";
  316.   static char rule_msg[] = "too many rules";
  317.   static char symbol_msg[] = "too many symbols";
  318.  
  319.   if (bp->class == UNKNOWN)
  320.     bp->class = NONTERMINAL;
  321.   else if (bp->class != NONTERMINAL)
  322.     error(lineno, lhs_msg);
  323.   if (bp->value == UNDEFINED)
  324.     {
  325.       if (nvars >= MAXSHORT) fatal(symbol_msg);
  326.       bp->value = nvars;
  327.       nvars++;
  328.     }
  329.   bp->used = 1;
  330.  
  331.   if (nrules >= MAXSHORT) fatal(rule_msg);
  332.   nrules++;
  333.   last_rule->assoc = assoc;
  334.   last_rule->prec = prec;
  335.   lhs = bp;
  336.   last_rule->next = rp = NEW(rule_cell);
  337.   last_rule = rp;
  338.   rp->lhs = bp;
  339.   assoc = 0;
  340.   prec = 0;
  341.   rhslen = 0;
  342.   last_symbol = NIL(rhs_cell);
  343. }
  344.  
  345. add_rhs(bp)
  346. register bucket *bp;
  347. {
  348.   register rhs_cell *rhsp;
  349.  
  350.   rhslen++;
  351.   rhsp = NEW(rhs_cell);
  352.   if (last_symbol)
  353.     last_symbol->next = rhsp;
  354.   else
  355.     last_rule->rhs = rhsp;
  356.   last_symbol = rhsp;
  357.   rhsp->symbol = bp;
  358.   bp->used = 1;
  359.   if (bp->class == TERMINAL)
  360.     {
  361.       assoc = bp->assoc;
  362.       prec = bp->prec;
  363.     }
  364. }
  365.  
  366. check_default_action()
  367. {
  368.   if (type_flag && lhs->tag != NIL(char))
  369.     {
  370.       if (rhslen == 0)
  371.     no_rhs_warning();
  372.       else if (lhs->tag != last_rule->rhs->symbol->tag)
  373.     default_type_clash();
  374.     }
  375. }
  376.  
  377. write_action(tp, bias, lhs_type)
  378. text *tp;
  379. int bias;
  380. char *lhs_type;
  381. {
  382.   register char *s, *end;
  383.   register int c;
  384.   register int k;
  385.   register char *local_type;
  386.   register rhs_cell *rhsp;
  387.   int m, n;
  388.   int negative;
  389.   int quote;
  390.   int inside;
  391.  
  392.   fprintf(action_file, "\n\tcase %d:", nrules - 1);
  393.   fprintf(action_file, "\n#line %d \"%s\"\n", tp->start_line, input_file_name);
  394.   s = tp->ch;
  395.   end = s + tp->length;
  396.   while (s < end)
  397.     {
  398.       c = *s;
  399.       if (c == '$')
  400.     {
  401.       local_type = NIL(char);
  402.       n = 0;
  403.       negative = 0;
  404.       c = *++s;
  405.       if (c == '<')
  406.         {
  407.           c = *++s;
  408.           switch (c)
  409.         {
  410.         case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
  411.         case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
  412.         case 'K':  case 'L':  case 'M':  case 'N':  case 'O':
  413.         case 'P':  case 'Q':  case 'R':  case 'S':  case 'T':
  414.         case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':
  415.         case 'Z':
  416.         case 'a':  case 'b':  case 'c':  case 'd':  case 'e':
  417.         case 'f':  case 'g':  case 'h':  case 'i':  case 'j':
  418.         case 'k':  case 'l':  case 'm':  case 'n':  case 'o':
  419.         case 'p':  case 'q':  case 'r':  case 's':  case 't':
  420.         case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
  421.         case 'z':
  422.         case '_':
  423.           local_type = s;
  424.           n = 1;
  425.           c = *++s;
  426.           break;
  427.  
  428.         default:
  429.           type_tag_error(tp, s);
  430.         }
  431.  
  432.           while (c != '>')
  433.         {
  434.           switch (c)
  435.             {
  436.             case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
  437.             case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
  438.             case 'K':  case 'L':  case 'M':  case 'N':  case 'O':
  439.             case 'P':  case 'Q':  case 'R':  case 'S':  case 'T':
  440.             case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':
  441.             case 'Z':
  442.             case 'a':  case 'b':  case 'c':  case 'd':  case 'e':
  443.             case 'f':  case 'g':  case 'h':  case 'i':  case 'j':
  444.             case 'k':  case 'l':  case 'm':  case 'n':  case 'o':
  445.             case 'p':  case 'q':  case 'r':  case 's':  case 't':
  446.             case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
  447.             case 'z':
  448.             case '0':  case '1':  case '2':  case '3':  case '4':
  449.             case '5':  case '6':  case '7':  case '8':  case '9':
  450.             case '_':
  451.               n++;
  452.               c = *++s;
  453.               break;
  454.  
  455.             default:
  456.               type_tag_error(tp, s);
  457.             }
  458.         }
  459.           c = *++s;
  460.         }
  461.       if (c == '$')
  462.         {
  463.           fprintf(action_file, "yyval");
  464.           if (local_type)
  465.         {
  466.           putc('.', action_file);
  467.           while (n > 0)
  468.             {
  469.               c = *local_type++;
  470.               putc(c, action_file);
  471.               n--;
  472.             }
  473.         }
  474.           else if (type_flag)
  475.         {
  476.           if (lhs_type == NIL(char))
  477.             lhs_type_error(tp, s);
  478.           fprintf(action_file, ".%s", lhs_type);
  479.         }
  480.           s++;
  481.         }
  482.       else
  483.         {
  484.           if (c == '-')
  485.         {
  486.           negative = 1;
  487.            c = *++s;
  488.         }
  489.  
  490.           if ( ! IS_NUMERIC(c))
  491.         dollar_error(tp, s);
  492.  
  493.           k = 0;
  494.           while (c == '0') c = *++s;
  495.           while (IS_NUMERIC(c))
  496.         {
  497.           k = 10*k + NUMERIC_VALUE(c);
  498.           c = *++s;
  499.         }
  500.  
  501.           if (negative) k = -k;
  502.           fprintf(action_file, "yyvp[%d]", k - bias);
  503.           if (k > 0)
  504.         {
  505.           if (k > rhslen)
  506.             rhs_error(tp, s, k, rhslen);
  507.           else
  508.             {
  509.               rhsp = last_rule->rhs;
  510.               m = k;
  511.               while (m > 1)
  512.             {
  513.               rhsp = rhsp->next;
  514.               m--;
  515.             }
  516.             }
  517.         }
  518.           if (local_type)
  519.         {
  520.           putc('.', action_file);
  521.           while (n > 0)
  522.             {
  523.               c = *local_type++;
  524.               putc(c, action_file);
  525.               n--;
  526.             }
  527.         }
  528.           else if (type_flag)
  529.         {
  530.           if (k <= 0 || rhsp->symbol->tag == NIL(char))
  531.             rhs_type_error(tp, s, k);
  532.           fprintf(action_file, ".%s", rhsp->symbol->tag);
  533.         }
  534.         }
  535.     }
  536.       else if (c == QUOTE || c == DOUBLE_QUOTE)
  537.     {
  538.       quote = c;
  539.       putc(c, action_file);
  540.       c = *++s;
  541.       while (c != quote)
  542.         {
  543.           putc(c, action_file);
  544.           if (c == BACKSLASH)
  545.         {
  546.           c = *++s;
  547.           putc(c, action_file);
  548.         }
  549.           c = *++s;
  550.         }
  551.       putc(c, action_file);
  552.       s++;
  553.     }
  554.       else if (c == '/')
  555.     {
  556.       putc(c, action_file);
  557.       c = *++s;
  558.       if (c == '*')
  559.         {
  560.           putc(c, action_file);
  561.           c = *++s;
  562.           inside = 1;
  563.           while (inside)
  564.         {
  565.           while (c != '*')
  566.             {
  567.               putc(c, action_file);
  568.               c = *++s;
  569.             }
  570.           putc(c, action_file);
  571.           c = *++s;
  572.           if (c == '/') inside = 0;
  573.         }
  574.           putc(c, action_file);
  575.           s++;
  576.         }
  577.     }
  578.       else
  579.     {
  580.       putc(c, action_file);
  581.       s++;
  582.     }
  583.     }
  584.  
  585.   fprintf(action_file, "\n\t\t\tbreak;\n");
  586. }
  587.  
  588. mid_action(tp)
  589. text *tp;
  590. {
  591.   register rule_cell *rp;
  592.   register rhs_cell *rhsp;
  593.   register bucket *bp;
  594.   register int i;
  595.   register char *s;
  596.   char name[32];
  597.   static char symbol_msg[] = "too many symbols";
  598.  
  599.   write_action(tp, rhslen + 1, NIL(char));
  600.   actname_count++;
  601.   sprintf(name, "$act%d", actname_count);
  602.   i = 0;
  603.   for (s = name; *s; s++) i++;
  604.   bp = make_bucket(IDENTIFIER, name, i);
  605.   bp->class = NONTERMINAL;
  606.   if (nvars >= MAXSHORT) fatal(symbol_msg);
  607.   bp->value = nvars;
  608.   nvars++;
  609.   bp->used = 1;
  610.  
  611.   rhsp = NEW(rhs_cell);
  612.   rhsp->symbol = bp;
  613.   if (last_symbol)
  614.     last_symbol->next = rhsp;
  615.   else
  616.     last_rule->rhs = rhsp;
  617.   last_symbol = rhsp;
  618.   rhslen++;
  619.  
  620.   rp = NEW(rule_cell);
  621.   rp->lhs = last_rule->lhs;
  622.   rp->rhs = last_rule->rhs;
  623.   last_rule->next = rp;
  624.   rp = last_rule;
  625.   last_rule = rp->next;
  626.   rp->lhs = bp;
  627.   rp->rhs = NIL(rhs_cell);
  628.   nrules++;
  629. }
  630.  
  631. char *
  632. skip_white_space2(s)
  633. register char *s;
  634. {
  635.   register int done, inside;
  636.  
  637.   done = 0;
  638.   while (!done)
  639.     {
  640.       switch (*s)
  641.     {
  642.     case SP:  case BS:  case HT:  case VT:  case FF:
  643.     case CR:  case NEWLINE:  case DEL:
  644.       s++;
  645.       break;
  646.  
  647.     case '/':
  648.       if (s[1] != '*')
  649.         done = 1;
  650.       else
  651.         {
  652.           s += 2;
  653.           inside = 1;
  654.           while (inside)
  655.         {
  656.           while (*s != '*') s++;
  657.           s++;
  658.           if (*s == '/')
  659.             {
  660.               s++;
  661.               inside = 0;
  662.             }
  663.         }
  664.         }
  665.       break;
  666.  
  667.     default:
  668.       done = 1;
  669.     }
  670.     }
  671.  
  672.   return (s);
  673. }
  674.  
  675. int
  676. is_default_action(tp)
  677. register text *tp;
  678. {
  679.   register char *s;
  680.   register int c;
  681.   register int result;
  682.  
  683.   result = 0;
  684.   s = skip_white_space2(tp->ch);
  685.   c = *s++;
  686.   if (c == '{')
  687.     {
  688.       s = skip_white_space2(s);
  689.       c = *s++;
  690.       if (c == '$')
  691.     {
  692.       c = *s++;
  693.       if (c == '$')
  694.         {
  695.           s = skip_white_space2(s);
  696.           c = *s++;
  697.           if (c == '=')
  698.         {
  699.           s = skip_white_space2(s);
  700.           c = *s++;
  701.           if (c == '$')
  702.             {
  703.               c = *s++;
  704.               while (c == '0') c = *s++;
  705.               if (c == '1')
  706.             {
  707.               s = skip_white_space2(s);
  708.               c = *s++;
  709.               if (c == ';')
  710.                 {
  711.                   s = skip_white_space2(s);
  712.                   c = *s;
  713.                   if (c == '}')
  714.                 result = 1;
  715.                 }
  716.             }
  717.             }
  718.         }
  719.         }
  720.     }
  721.       else if (c == '}')
  722.     result = 1;
  723.     }
  724.   else if (c == '$')
  725.     {
  726.       c = *s++;
  727.       if (c == '$')
  728.     {
  729.       s = skip_white_space2(s);
  730.       c = *s++;
  731.       if (c == '=')
  732.         {
  733.           s = skip_white_space2(s);
  734.           c = *s++;
  735.           if (c == '$')
  736.         {
  737.           c = *s++;
  738.           while (c == '0') c = *s++;
  739.           if (c == '1')
  740.             {
  741.               s = skip_white_space2(s);
  742.               c = *s;
  743.               if (c == ';')
  744.             result = 1;
  745.             }
  746.         }
  747.         }
  748.     }
  749.     }
  750.   else if (c == ';')
  751.     result = 1;
  752.  
  753.   return (result);
  754. }
  755.  
  756. end_action(tp)
  757. text *tp;
  758. {
  759.   if (!is_default_action(tp))
  760.     {
  761.       write_action(tp, 1, last_rule->lhs->tag);
  762.     }
  763. }
  764.  
  765. read_grammar()
  766. {
  767.   register int tok;
  768.   register bucket *bp;
  769.   register text *tp;
  770.   static char rule_msg[] = "malformed rule";
  771.   static char prec_msg[] = "undefined precedence specifier";
  772.  
  773.   tok = yylex();
  774.   while (tok == TEXT)
  775.     {
  776.       write_text(yylval.tp, action_file);
  777.       free_text(yylval.tp);
  778.       tok = yylex();
  779.     }
  780.  
  781.   define_error_code();
  782.   define_stype();
  783.   copy_section(action_file);
  784.  
  785.   if (tok != IDENTIFIER)
  786.     error(lineno, rule_msg);
  787.  
  788.   if (goal == NIL(bucket))
  789.     goal = yylval.bp;
  790.  
  791.   initialize_grammar();
  792.   add_rule(yylval.bp);
  793.   tok = yylex();
  794.   if (tok != COLON)
  795.     error(lineno, rule_msg);
  796.   tok = yylex();
  797.  
  798.   while (tok != END_OF_FILE && tok != MARK)
  799.     {
  800.       switch (tok)
  801.     {
  802.     case IDENTIFIER:
  803.       bp = yylval.bp;
  804.       tok = yylex();
  805.       if (tok == COLON)
  806.         {
  807.           check_default_action();
  808.           add_rule(bp);
  809.           tok = yylex();
  810.         }
  811.       else
  812.         add_rhs(bp);
  813.       break;
  814.  
  815.     case CHARACTER:
  816.     case STRING:
  817.       add_rhs(yylval.bp);
  818.       tok = yylex();
  819.       break;
  820.  
  821.     case BAR:
  822.       check_default_action();
  823.       add_rule(lhs);
  824.       tok = yylex();
  825.       break;
  826.  
  827.     case ACTION:
  828.       tp = yylval.tp;
  829.       tok = yylex();
  830.       switch (tok)
  831.         {
  832.         case END_OF_FILE:
  833.           end_action(tp);
  834.           break;
  835.  
  836.         case IDENTIFIER:
  837.           bp = yylval.bp;
  838.           tok = yylex();
  839.           if (tok == COLON)
  840.         {
  841.           end_action(tp);
  842.           add_rule(bp);
  843.           tok = yylex();
  844.         }
  845.           else
  846.         {
  847.           mid_action(tp);
  848.           add_rhs(bp);
  849.         }
  850.           break;
  851.  
  852.         case BAR:
  853.           end_action(tp);
  854.           add_rule(lhs);
  855.           tok = yylex();
  856.           break;
  857.  
  858.         case SEMICOLON:
  859.           end_action(tp);
  860.           while (tok == SEMICOLON)
  861.             tok = yylex();
  862.           if (tok == IDENTIFIER)
  863.         {
  864.           add_rule(yylval.bp);
  865.           tok = yylex();
  866.           if (tok != COLON)
  867.             error(lineno, rule_msg);
  868.           tok = yylex();
  869.         }
  870.           break;
  871.  
  872.         case CHARACTER:
  873.         case STRING:
  874.         case ACTION:
  875.         case PREC:
  876.           mid_action(tp);
  877.           break;
  878.  
  879.         default:
  880.           error(lineno, rule_msg);
  881.         }
  882.       break;
  883.  
  884.     case PREC:
  885.       tok = yylex();
  886.       if (tok != IDENTIFIER && tok != CHARACTER && tok != STRING)
  887.         error(lineno, rule_msg);
  888.       bp = yylval.bp;
  889.       if (bp->prec == 0)
  890.         error(lineno, prec_msg);
  891.       assoc = bp->assoc;
  892.       prec = bp->prec;
  893.       tok = yylex();
  894.       if (tok == ACTION)
  895.         {
  896.           end_action(yylval.tp);
  897.           tok = yylex();
  898.         }
  899.       while (tok == SEMICOLON)
  900.         tok = yylex();
  901.       if (tok == IDENTIFIER)
  902.         {
  903.           add_rule(yylval.bp);
  904.           tok = yylex();
  905.           if (tok != COLON)
  906.         error(lineno, rule_msg);
  907.           tok = yylex();
  908.         }
  909.       else if (tok == BAR)
  910.         {
  911.           add_rule(lhs);
  912.           tok = yylex();
  913.         }
  914.       break;
  915.  
  916.     case SEMICOLON:
  917.       while (tok == SEMICOLON)
  918.         tok = yylex();
  919.       if (tok == IDENTIFIER)
  920.         {
  921.           add_rule(yylval.bp);
  922.           tok = yylex();
  923.           if (tok != COLON)
  924.         error(lineno, rule_msg);
  925.           tok = yylex();
  926.         }
  927.       break;
  928.  
  929.     default:
  930.       error(lineno, rule_msg);
  931.     }
  932.     }
  933.  
  934.   copy_section(action_file);
  935.   fprintf(action_file, "#line %d \"%s\"\n", lineno, input_file_name);
  936.   while ((tok = getc(input_file)) != EOF)  putc(tok, action_file);
  937.   last_rule->assoc = assoc;
  938.   last_rule->prec = prec;
  939. }
  940.  
  941. print_grammar()
  942. {
  943.   register rule_cell *rp;
  944.   register rhs_cell *rhsp;
  945.   register int k, n;
  946.   register int spacing;
  947.   register bucket *lhs;
  948.  
  949.   spacing = 0;
  950.   for (rp = grammar->next; rp; rp = rp->next)
  951.     {
  952.       k = rp->lhs->length;
  953.       if (k > spacing) spacing = k;
  954.     }
  955.   spacing++;
  956.  
  957.   lhs = NIL(bucket);
  958.   k = 0;
  959.   for (rp = grammar->next; rp; rp = rp->next)
  960.     {
  961.       k++;
  962.       if (rp->lhs == lhs)
  963.     {
  964.       fprintf(verbose_file, "%4d\t", k);
  965.       for (n = spacing; n > 0; n--) putc(SP, verbose_file);
  966.       putc('|', verbose_file);
  967.       putc(SP, verbose_file);
  968.     }
  969.       else
  970.     {
  971.       lhs = rp->lhs;
  972.       fprintf(verbose_file, "\n%4d\t%s", k, lhs->key);
  973.       for (n = spacing - lhs->length; n > 0; n--) putc(SP, verbose_file);
  974.       putc(':', verbose_file);
  975.       putc(SP, verbose_file);
  976.     }
  977.  
  978.       for (rhsp = rp->rhs; rhsp; rhsp = rhsp->next)
  979.     fprintf(verbose_file, " %s", rhsp->symbol->prname);
  980.  
  981.       putc(NEWLINE, verbose_file);
  982.     }
  983.  
  984.   if (k + 1 != nrules)
  985.     panic("print_grammar");
  986. }
  987.  
  988. check_symbols()
  989. {
  990.   register bucket *bp;
  991.  
  992.   if ( ! goal->used)
  993.     no_goal(goal);
  994.   for (bp = first_symbol; bp; bp = bp->next)
  995.     {
  996.       if (bp->form == IDENTIFIER && bp->class == UNKNOWN)
  997.     {
  998.       undefined_warning(bp);
  999.       bp->class = TERMINAL;
  1000.     }
  1001.     }
  1002. }
  1003.  
  1004. number_symbols()
  1005. {
  1006.   register bucket *bp;
  1007.   register int number;
  1008.   register int c;
  1009.   static char token_msg[] = "too_many_tokens";
  1010.   static char symbol_msg[] = "too_many_symbols";
  1011.  
  1012.   number = MAXCHAR + 1;
  1013.   nsyms = 1;
  1014.   for (bp = first_symbol; bp; bp = bp->next)
  1015.     {
  1016.       if (bp->class == TERMINAL && bp->used)
  1017.     {
  1018.       bp->index = nsyms;
  1019.       if (nsyms >= MAXSHORT) fatal(symbol_msg);
  1020.       nsyms++;
  1021.       if (bp->value == UNDEFINED)
  1022.         {
  1023.           if (bp->form == CHARACTER)
  1024.         {
  1025.           c = bp->key[0];
  1026.           if (BIT(numbers_used, c))
  1027.             revalued_warning(bp);
  1028.           bp->value = c;
  1029.         }
  1030.           else
  1031.         {
  1032.           if (number >= MAX_TOKEN_NUMBER) fatal(token_msg);
  1033.           number++;
  1034.           while (BIT(numbers_used, number))
  1035.             {
  1036.               if (number >= MAX_TOKEN_NUMBER) fatal(token_msg);
  1037.               number++;
  1038.             }
  1039.           bp->value = number;
  1040.         }
  1041.         }
  1042.     }
  1043.     }
  1044.   ntokens = nsyms;
  1045.   start_symbol = nsyms;
  1046.   for (bp = first_symbol; bp; bp = bp->next)
  1047.     {
  1048.       if (bp->class == NONTERMINAL)
  1049.     {
  1050.       if (nsyms >= MAXSHORT) fatal(symbol_msg);
  1051.       bp->index = bp->value + start_symbol;
  1052.       nsyms++;
  1053.     }
  1054.     }
  1055. }
  1056.  
  1057. int
  1058. is_C_identifier(s, n)
  1059. register char *s;
  1060. int n;
  1061. {
  1062.   register int i;
  1063.   register int result;
  1064.  
  1065.   result = 0;
  1066.   if (n > 0)
  1067.     {
  1068.       switch (s[0])
  1069.     {
  1070.     case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
  1071.     case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
  1072.     case 'K':  case 'L':  case 'M':  case 'N':  case 'O':
  1073.     case 'P':  case 'Q':  case 'R':  case 'S':  case 'T':
  1074.     case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':
  1075.     case 'Z':
  1076.     case 'a':  case 'b':  case 'c':  case 'd':  case 'e':
  1077.     case 'f':  case 'g':  case 'h':  case 'i':  case 'j':
  1078.     case 'k':  case 'l':  case 'm':  case 'n':  case 'o':
  1079.     case 'p':  case 'q':  case 'r':  case 's':  case 't':
  1080.     case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
  1081.     case 'z':
  1082.     case '_':
  1083.       result = 1;
  1084.     }
  1085.     }
  1086.  
  1087.   for (i = 1; i < n && result; i++)
  1088.     {
  1089.       switch (s[i])
  1090.     {
  1091.         case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
  1092.         case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
  1093.         case 'K':  case 'L':  case 'M':  case 'N':  case 'O':
  1094.         case 'P':  case 'Q':  case 'R':  case 'S':  case 'T':
  1095.         case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':
  1096.         case 'Z':
  1097.         case 'a':  case 'b':  case 'c':  case 'd':  case 'e':
  1098.         case 'f':  case 'g':  case 'h':  case 'i':  case 'j':
  1099.         case 'k':  case 'l':  case 'm':  case 'n':  case 'o':
  1100.         case 'p':  case 'q':  case 'r':  case 's':  case 't':
  1101.         case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
  1102.         case 'z':
  1103.         case '0':  case '1':  case '2':  case '3':  case '4':
  1104.         case '5':  case '6':  case '7':  case '8':  case '9':
  1105.         case '_':
  1106.           break;
  1107.  
  1108.         default:
  1109.           result = 0;
  1110.         }
  1111.     }
  1112.  
  1113.   return(result);
  1114. }
  1115.  
  1116. define_symbols()
  1117. {
  1118.   register bucket *bp;
  1119.   register int c;
  1120.   register int eq;
  1121.   register int max;
  1122.  
  1123.   max =0;
  1124.   for (bp = first_symbol->next; bp; bp = bp->next)
  1125.     {
  1126.       if (bp->value > max) max = bp->value;
  1127.       if (bp->class == TERMINAL && bp->form != CHARACTER)
  1128.     {
  1129.       if (bp->value != UNDEFINED && is_C_identifier(bp->key, bp->length))
  1130.       {
  1131.         fprintf(output_file, "\n#define\t%s\t%d", bp->key, bp->value);
  1132.         if (dflag)
  1133.           fprintf(temp_file, "\n#define\t%s\t%d", bp->key, bp->value);
  1134.       }
  1135.     }
  1136.     }
  1137.   fprintf(output_file, "\n#define\tYYMAXTOK\t%d\n", max);
  1138.   if (!dflag) return;
  1139.   fprintf(temp_file, "\n#define\tYYMAXTOK\t%d\n", max);
  1140.   if (temp_file == defines_file)
  1141.     fclose(temp_file);
  1142.   else
  1143.     {
  1144.       fclose(temp_file);
  1145.       temp_file = fopen(temp_file_name, "r");
  1146.       if (temp_file == NULL) open_error(temp_file_name);
  1147.       c = getc(defines_file);
  1148.       eq = (c == getc(temp_file));
  1149.       while (eq && c != EOF)
  1150.     {
  1151.       c = getc(defines_file);
  1152.       eq = (c == getc(temp_file));
  1153.     }
  1154.       fclose(defines_file);
  1155.       fclose(temp_file);
  1156.       if ( ! eq)
  1157.     {
  1158.       defines_file = fopen(defines_file_name, "w");
  1159.       if (defines_file == NULL) open_error(defines_file_name);
  1160.       temp_file = fopen(temp_file_name, "r");
  1161.       if (temp_file == NULL) open_error(temp_file_name);
  1162.       c = getc(temp_file);
  1163.       while (c != EOF)
  1164.         {
  1165.           putc(c, defines_file);
  1166.           c = getc(temp_file);
  1167.         }
  1168.     }
  1169.     }
  1170.   defines_file = NIL(FILE);
  1171.   temp_file = NIL(FILE);
  1172. }
  1173.  
  1174. pack_symbols()
  1175. {
  1176.   register int n;
  1177.   register bucket *bp;
  1178.  
  1179.   symbol_name = NEW2(nsyms, char *);
  1180.   symbol_value = NEW2(nsyms, short);
  1181.   symbol_prec = NEW2(nsyms, short);
  1182.   symbol_assoc = NEW2(nsyms, char);
  1183.  
  1184.   symbol_name[0] = mk_prname(IDENTIFIER, "$eof", 4);
  1185.   symbol_value[0] = 0;
  1186.  
  1187.   symbol_name[start_symbol] = augmenting_symbol->prname;
  1188.   symbol_value[start_symbol] = augmenting_symbol->value;
  1189.  
  1190.   for (bp = first_symbol; bp; bp = bp->next)
  1191.     {
  1192.       n = bp->index;
  1193.       if (n != 0)
  1194.     {
  1195.       symbol_name[n] = bp->prname;
  1196.       symbol_value[n] = bp->value;
  1197.       symbol_prec[n] = bp->prec;
  1198.       symbol_assoc[n] = bp->assoc;
  1199.       bp->key = NIL(char);
  1200.     }
  1201.     }
  1202. }
  1203.  
  1204. int
  1205. item_count()
  1206. {
  1207.   register rule_cell *rp;
  1208.   register rhs_cell *rhsp;
  1209.   register int count;
  1210.  
  1211.   count = 1;
  1212.   for (rp = grammar; rp; rp = rp->next)
  1213.     {
  1214.       count++;
  1215.       for (rhsp = rp->rhs; rhsp; rhsp = rhsp->next) count++;
  1216.     }
  1217.  
  1218.   return (count);
  1219. }
  1220.  
  1221. pack_grammar()
  1222. {
  1223.   register rule_cell *rp;
  1224.   register rhs_cell *rhsp;
  1225.   register int m, n;
  1226.  
  1227.   nitems = item_count();
  1228.   if (nitems > MAXSHORT)
  1229.     fatal("grammar too large");
  1230.   ritem = NEW2(nitems, short);
  1231.   rlhs = NEW2(nrules, short);
  1232.   rrhs = NEW2(nrules + 1, short);
  1233.   rprec = NEW2(nrules, short);
  1234.   rassoc = NEW2(nrules, char);
  1235.  
  1236.   m = 0;
  1237.   n = 1;
  1238.   for (rp = grammar; rp; rp = rp->next)
  1239.     {
  1240.       rlhs[m] = rp->lhs->index;
  1241.       rrhs[m] = n;
  1242.       rprec[m] = rp->prec;
  1243.       rassoc[m] = rp->assoc;
  1244.       for (rhsp = rp->rhs; rhsp; rhsp = rhsp->next)
  1245.     {
  1246.       ritem[n] = rhsp->symbol->index;
  1247.       n++;
  1248.     }
  1249.       ritem[n] = -m;
  1250.       n++;
  1251.       m++;
  1252.     }
  1253.   rrhs[m] = n;
  1254. }
  1255.  
  1256. free_grammar()
  1257. {
  1258.   register rule_cell *rp, *trp;
  1259.   register rhs_cell *rhsp, *trhsp;
  1260.  
  1261.   for (rp = grammar; rp; rp = trp)
  1262.     {
  1263.       for (rhsp = rp->rhs; rhsp; rhsp = trhsp)
  1264.     {
  1265.       trhsp = rhsp->next;
  1266.       FREE(rhsp);
  1267.     }
  1268.       trp = rp->next;
  1269.       FREE(rp);
  1270.     }
  1271. }
  1272.  
  1273. reader()
  1274. {
  1275.   numbers_used = NEW2(WORDSIZE(MAX_TOKEN_NUMBER + 1), unsigned);
  1276.   stype = NIL(text);
  1277.   augmenting_symbol = make_bucket(IDENTIFIER, "S'", 2);
  1278.   FREE(augmenting_symbol->prname);
  1279.   augmenting_symbol->prname = NEW2(3, char);
  1280.   augmenting_symbol->prname[0] = 'S';
  1281.   augmenting_symbol->prname[1] = QUOTE;
  1282.   type_flag = 0;
  1283.   actname_count = 0;
  1284.   copy_section(output_file);
  1285.   read_declarations();
  1286.   read_grammar();
  1287.   check_symbols();
  1288.   number_symbols();
  1289.   FREE(numbers_used);
  1290.   define_symbols();
  1291.   if (vflag) print_grammar();
  1292.   pack_symbols();
  1293.   pack_grammar();
  1294.   free_symtab();
  1295.   free_grammar();
  1296. }
  1297.